﻿using Microsoft.AspNetCore.Components.Authorization;
using MXERP.Shared.Security;
using System.Security.Claims;
using System.Text.Json;

namespace MXERP.Infrastructure.Authentication
{
    public class CustomStateProvider : AuthenticationStateProvider
    {
        private readonly ILocalStorageService _localStorageService;

        public CustomStateProvider(ILocalStorageService localStorageService)
        {
            _localStorageService = localStorageService;
        }

        public async Task StateChangedAsync()
        {
            var authState = Task.FromResult(await GetAuthenticationStateAsync());
            NotifyAuthenticationStateChanged(authState);
        }

        public void MarkUserAsLoggedOut()
        {
            var anonymousUser = new ClaimsPrincipal(new ClaimsIdentity());
            var authState = Task.FromResult(new AuthenticationState(anonymousUser));

            NotifyAuthenticationStateChanged(authState);
        }

        public async Task<ClaimsPrincipal> GetAuthenticationStateProviderUserAsync()
        {
            var state = await GetAuthenticationStateAsync();
            var authenticationStateProviderUser = state.User;
            return authenticationStateProviderUser;
        }

        public ClaimsPrincipal AuthenticationStateUser { get; set; } = default!;

        public override async Task<AuthenticationState> GetAuthenticationStateAsync()
        {
            var token = await _localStorageService.GetItemAsync<string>(StorageConstant.Local.AuthToken);
            if (string.IsNullOrWhiteSpace(token))
            {
                return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity()));
            }
            //_flurlClient.Settings(savedToken);
            //_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", savedToken);
            var state = new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity(GetClaimsFromJwt(token), "jwt")));
            AuthenticationStateUser = state.User;
            return state;
        }

        private IEnumerable<Claim> GetClaimsFromJwt(string jwt)
        {
            var claims = new List<Claim>();
            var payload = jwt.Split('.')[1];
            var jsonBytes = ParseBase64WithoutPadding(payload);
            var keyValuePairs = JsonSerializer.Deserialize<Dictionary<string, object>>(jsonBytes);

            if (keyValuePairs != null)
            {
                //keyValuePairs.TryGetValue(ClaimTypes.Role, out var roles);

                //if (roles != null)
                //{
                //    if (roles.ToString().Trim().StartsWith("["))
                //    {
                //        var parsedRoles = JsonSerializer.Deserialize<string[]>(roles.ToString());

                //        claims.AddRange(parsedRoles.Select(role => new Claim(ClaimTypes.Role, role)));
                //    }
                //    else
                //    {
                //        claims.Add(new Claim(ClaimTypes.Role, roles.ToString()));
                //    }

                //    keyValuePairs.Remove(ClaimTypes.Role);
                //}

                keyValuePairs.TryGetValue(MXERPClaimTypes.License, out var licenses);
                if (licenses != null)
                {
                    var strLicenses = licenses.ToString()!;
                    if (strLicenses.Trim().StartsWith("["))
                    {
                        var parsedLicensess = JsonSerializer.Deserialize<string[]>(strLicenses);
                        if (parsedLicensess?.Length > 0)
                        {
                            claims.AddRange(parsedLicensess.Select(license => new Claim(MXERPClaimTypes.License, license)));
                        }
                    }
                    else
                    {
                        claims.Add(new Claim(MXERPClaimTypes.License, strLicenses));
                    }
                    keyValuePairs.Remove(MXERPClaimTypes.License);
                }

                claims.AddRange(keyValuePairs.Select(kvp => new Claim(kvp.Key, kvp.Value.ToString()!)));
            }
            return claims;
        }

        private byte[] ParseBase64WithoutPadding(string payload)
        {
            payload = payload.Trim().Replace('-', '+').Replace('_', '/');
            var base64 = payload.PadRight(payload.Length + (4 - payload.Length % 4) % 4, '=');
            return Convert.FromBase64String(base64);
        }
    }
}